#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <LibLOL.c>
#include <wiilight.h>
#include <ctype.h>

#include <ogc/conf.h>
#include <ogc/pad.h>


#include "fat.h"
#include "nand.h"
#include "restart.h"
#include "title.h"
#include "usbstorage.h"
#include "utils.h"
#include "video.h"
#include "wad.h"
#include "wpad.h"
#include "globals.h"


/* FAT device list  */
//static fatDevice fdevList[] = {
fatDevice fdevList[] = {
	{ "sd",		"Wii SD ",			&__io_wiisd },
	{ "usb2",	"USB2 ",	                        &__io_usb2storage},
	{ "usb",	"USB",	                        &__io_usbstorage},
};

/* NAND device list */
//static nandDevice ndevList[] = {
nandDevice ndevList[] = {
	{ "Non",				0,	0x00,	0x00 },
	{ "SD",			                1,      0xF0,	0xF1 },
	{ "USB 2.0",	                        2,	0xF2,	0xF3 },
};


/* FAT device */
static fatDevice  *fdev = NULL;
static nandDevice *ndev = NULL;

// wiiNinja: Define a buffer holding the previous path names as user
// traverses the directory tree. Max of 10 levels is define at this point
static u8 gDirLevel = 0;
static char gDirList [MAX_DIR_LEVELS][MAX_FILE_PATH_LEN];
static s32  gSeleted[MAX_DIR_LEVELS];
static s32  gStart[MAX_DIR_LEVELS];

/* Macros */
#define NB_FAT_DEVICES		(sizeof(fdevList) / sizeof(fatDevice))
#define NB_NAND_DEVICES		(sizeof(ndevList) / sizeof(nandDevice))

// Local prototypes: wiiNinja
void WaitPrompt (char *prompt);
int PushCurrentDir(char *dirStr, s32 Selected, s32 Start);
char *PopCurrentDir(s32 *Selected, s32 *Start);
bool IsListFull (void);
char *PeekCurrentDir (void);
u32 WaitButtons(void);
u32 Pad_GetButtons(void);
void WiiLightControl (int state);

s32 __Menu_IsGreater(const void *p1, const void *p2)
{
	u32 n1 = *(u32 *)p1;
	u32 n2 = *(u32 *)p2;

	/* Equal */
	if (n1 == n2)
		return 0;

	return (n1 > n2) ? 1 : -1;
}


s32 __Menu_EntryCmp(const void *p1, const void *p2)
{
	fatFile *f1 = (fatFile *)p1;
	fatFile *f2 = (fatFile *)p2;

	/* Compare entries */ // wiiNinja: Include directory
    if ((f1->filestat.st_mode & S_IFDIR) && !(f2->filestat.st_mode & S_IFDIR))
        return (-1);
    else if (!(f1->filestat.st_mode & S_IFDIR) && (f2->filestat.st_mode & S_IFDIR))
        return (1);
    else
        return strcmp(f1->filename, f2->filename);
}

char gFileName[MAX_FILE_PATH_LEN];
s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen)
{
	fatFile  *buffer = NULL;
	DIR_ITER *dir    = NULL;

	struct stat filestat;

	//char dirpath[256], filename[768];
	u32  cnt;

	/* Generate dirpath */
	//sprintf(dirpath, "%s:" WAD_DIRECTORY, fdev->mount);

	/* Open directory */
	dir = diropen(inPath);
	if (!dir)
		return -1;

	/* Count entries */
	for (cnt = 0; !dirnext(dir, gFileName, &filestat);) {
		// if (!(filestat.st_mode & S_IFDIR)) // wiiNinja
			cnt++;
	}

	if (cnt > 0) {
		/* Allocate memory */
		buffer = malloc(sizeof(fatFile) * cnt);
		if (!buffer) {
			dirclose(dir);
			return -2;
		}

		/* Reset directory */
		dirreset(dir);

		/* Get entries */
		for (cnt = 0; !dirnext(dir, gFileName, &filestat);)
		{
			bool addFlag = false;
			
			if (filestat.st_mode & S_IFDIR)  // wiiNinja
            {
                // Add only the item ".." which is the previous directory
                // AND if we're not at the root directory
                if ((strcmp (gFileName, "..") == 0) && (gDirLevel > 1))
                    addFlag = true;
                else if (strcmp (gFileName, ".") != 0)
                    addFlag = true;
            }
            else
			{
				if(strlen(gFileName)>4)
				{
					if(!stricmp(gFileName+strlen(gFileName)-4, ".wad"))
						addFlag = true;
				}
			}

            if (addFlag == true)
            {
				fatFile *file = &buffer[cnt++];

				/* File name */
				strcpy(file->filename, gFileName);

				/* File stats */
				file->filestat = filestat;
			}
		}

		/* Sort list */
		qsort(buffer, cnt, sizeof(fatFile), __Menu_EntryCmp);
	}

	/* Close directory */
	dirclose(dir);

	/* Set values */
	*outbuf = buffer;
	*outlen = cnt;

	return 0;
}


void Menu_SelectIOS(void)
{WiiLightControl (WII_LIGHT_ON);
	u8 *iosVersion = NULL;
	u32 iosCnt;
	u8 tmpVersion;

	u32 cnt;
	s32 ret, selected = 0;
	bool found = false;

	/* Get IOS versions */
	ret = Title_GetIOSVersions(&iosVersion, &iosCnt);
	if (ret < 0)
		return;

	/* Sort list */
	qsort(iosVersion, iosCnt, sizeof(u8), __Menu_IsGreater);

	if (gConfig.cIOSVersion < 0)
		tmpVersion = CIOS_VERSION;
	else
	{
		tmpVersion = (u8)gConfig.cIOSVersion;
		// For debugging only
		//printf ("User pre-selected cIOS: %i\n", tmpVersion);
		//WaitButtons();
	}

	/* Set default version */
	for (cnt = 0; cnt < iosCnt; cnt++) {
		u8 version = iosVersion[cnt];

		/* Custom IOS available */
		//if (version == CIOS_VERSION)
		if (version == tmpVersion)
		{
			selected = cnt;
			found = true;
			break;
		}

		/* Current IOS */
		if (version == IOS_GetVersion())
			selected = cnt;
	}



        /* Ask user for IOS version */
        if ((gConfig.cIOSVersion < 0) || (found == false))
        {
                for (;;)


                {
        switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
                /* Clear console */
Con_FgColor(0, 0);
                Con_Clear();
                
                printf("\t>> Selection de la version de l'ios : < IOS%d >\n\n", iosVersion[selected]);


                printf("\t   Appuyez sur GAUCHE/DROITE pour changer la version de l'ios.\n\n");


                printf("\t   Appuyez sur A pour continuer.\n");
                printf("\t   Appuyez sur HOME ou START pour redemarrer.\n\n");
                break;
        default:case CONF_LANG_ENGLISH:
        /* Clear console */
Con_FgColor(0, 0);
                Con_Clear();
                
                printf("\t>> Select ios version: < IOS%d >\n\n", iosVersion[selected]);


                printf("\t   Press LEFT/RIGHT for change ios version.\n\n");


                printf("\t   Press A to continue.\n");
                printf("\t   Press HOME ou START HOME or START for restart.\n\n");
                break;

}
                        u32 buttons = WaitButtons();

			/* LEFT/RIGHT buttons */
			if (buttons & WPAD_BUTTON_LEFT) {
				if ((--selected) <= -1)
					selected = (iosCnt - 1);
			}
			if (buttons & WPAD_BUTTON_RIGHT) {
				if ((++selected) >= iosCnt)
					selected = 0;
			}

			/* HOME button */
			if (buttons & WPAD_BUTTON_HOME)
				Restart();

			/* A button */
			if (buttons & WPAD_BUTTON_A)
				break;
		}
	}


	u8 version = iosVersion[selected];

	if (IOS_GetVersion() != version) {
		/* Shutdown subsystems */
		Wpad_Disconnect();

		/* Load IOS */
		ret = IOS_ReloadIOS(version);

		/* Initialize subsystems */
		Wpad_Init();
	}
}


void Menu_FatDevice(void)
{       WiiLightControl (WII_LIGHT_ON);
	s32 ret, selected = 0;

	/* Unmount FAT device */
	if (fdev)
		Fat_Unmount(fdev);

	/* Select source device */
	if (gConfig.fatDeviceIndex < 0)
	{
		for (;;) {
			/* Clear console */
			Con_Clear();

			/* Selected device */
			fdev = &fdevList[selected];
Con_FgColor(0, 0);
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
                printf("\t>> Selection de l'emplacement du repertoire ISWAD: < %s >\n\n", fdev->name);


                printf("\t   Appuyez sur GAUCHE/DROITE pour changer l'emplacement.\n\n");


                printf("\t   Appuyez sur A pour continuer.\n");
                printf("\t   Appuyez sur B pour retourner au menu.\n\n");
                printf("\t   Appuyez sur HOME ou START pour redemarrer.\n\n");
break;
        default:case CONF_LANG_ENGLISH:


                printf("\t>> Select the location of ISWAD folder: < %s >\n\n", fdev->name);


                printf("\t   Press LEFT/RIGHT for change the location.\n\n");


                printf("\t   Press A to continue.\n");
                printf("\t   Press B for return to menu.\n\n");
                printf("\t   Press HOME or START for restart.\n\n");
                break;
}                     u32 buttons = WaitButtons();

			/* LEFT/RIGHT buttons */
			if (buttons & WPAD_BUTTON_LEFT) {
				if ((--selected) <= -1)
					selected = (NB_FAT_DEVICES - 1);
			}
			if (buttons & WPAD_BUTTON_RIGHT) {
				if ((++selected) >= NB_FAT_DEVICES)
					selected = 0;
			}

			/* HOME button */
			if (buttons & WPAD_BUTTON_HOME)
				Restart();

			/* A button */
			if (buttons & WPAD_BUTTON_A)
				break;
		}
	}
	else
	{
		fdev = &fdevList[gConfig.fatDeviceIndex];
	}
      
        printf("[+] Montage, attendez...");
        

        fflush(stdout);




        /* Mount FAT device */
	ret = Fat_Mount(fdev);
	if (ret < 0) {Con_FgColor(1, 5);
		printf(" ERREUR! Peripherique absent\n");
		goto err;
	} else  Con_FgColor(2, 5);
		printf(" OK!\n");

	return;


err:
        WiiLightControl (WII_LIGHT_OFF);

        printf("\n");
        printf("   Appuyez sur un bouton pour continuer...\n");
      
        
        WaitButtons();


        /* Prompt menu again */
        Menu_FatDevice();
}


void Menu_NandDevice(void)
{WiiLightControl (WII_LIGHT_ON);
	s32 ret, selected = 0;

	/* Disable NAND emulator */
	if (ndev) {
		Nand_Unmount(ndev);
		Nand_Disable();
	}

	/* Select source device */
	if (gConfig.nandDeviceIndex < 0)
	{
		for (;;) {
			/* Clear console */
			Con_Clear();

			/* Selected device */
			ndev = &ndevList[selected];
Con_FgColor(0, 0);
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
                printf("\t>> Selection de l'emplacement de la NAND: < %s >\n\n", ndev->name);


                printf("\t   Appuyez sur GAUCHE/DROITE pour changer l'emplacement.\n\n");


                printf("\t   Appuyez sur A pour continuer.\n");
                printf("\t   Appuyez sur B pour retourner au menu.\n\n");
                printf("\t   Appuyez sur HOME ou START pour redemarrer.\n\n");
                break;
        default:case CONF_LANG_ENGLISH:
    


                printf("\t>> Select the location of NAND: < %s >\n\n", ndev->name);


        printf("\t   Press LEFT/RIGHT for change the location.\n\n");


                printf("\t   Press A to continue.\n");
                printf("\t   Press B for return to menu.\n\n");
                printf("\t   Press HOME or START for restart.\n\n");
                break;
}




                        u32 buttons = WaitButtons();


                        /* LEFT/RIGHT buttons */
                        if (buttons & WPAD_BUTTON_LEFT) {
                                if ((--selected) <= -1)
                                        selected = (NB_NAND_DEVICES - 1);
                        }
                        if (buttons & WPAD_BUTTON_RIGHT) {
                                if ((++selected) >= NB_NAND_DEVICES)
                                        selected = 0;
                        }


                        /* HOME button */
                        if (buttons & WPAD_BUTTON_HOME)
                                Restart();


                        /* A button */
                        if (buttons & WPAD_BUTTON_A)
                                break;
                }
        }
        else
        {
                ndev = &ndevList[gConfig.nandDeviceIndex];
        }

        /* No NAND device */
        if (!ndev->mode)
                return;
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:

        printf("[+] Lancement NAND emulateur...");
        fflush(stdout);


        /* Mount NAND device */
        ret = Nand_Mount(ndev);
        if (ret < 0) {Con_FgColor(1, 5);
                printf(" ERREUR! Peripherique absent!\n");
                goto err;
        }


        /* Enable NAND emulator */
        ret = Nand_Enable(ndev);
        if (ret < 0) {Con_FgColor(1, 5);
                printf(" ERREUR! NAND absente!\n");
                goto err;
        } else Con_FgColor(2, 5);
                printf(" OK!\n");
                
                break;
        default:case CONF_LANG_ENGLISH:
        

        printf("[+] Launch NAND emulator...");
        fflush(stdout);


        /* Mount NAND device */
        ret = Nand_Mount(ndev);
        if (ret < 0) {
                printf(" ERROR! Missing Peripheral!\n");
                goto err;
        }


        /* Enable NAND emulator */
        ret = Nand_Enable(ndev);
        if (ret < 0) {
                printf(" ERROR! Missing NAND !\n");
                goto err;
        } else
                printf(" OK!\n");
                
                break;
}


        return;


err:
WiiLightControl (WII_LIGHT_OFF);
        switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
        printf("\n");
        printf("    Appuyez sur un bouton pour continuer...\n");
        break;
        default:case CONF_LANG_ENGLISH:
        printf("\n");
        printf("    Press a button to continue...\n");
        break;
}
        WaitButtons();


        /* Prompt menu again */
	Menu_NandDevice();
}

char gTmpFilePath[MAX_FILE_PATH_LEN];
/* Install and/or Uninstall multiple WADs - Leathl */
int Menu_BatchProcessWads(fatFile *files, int fileCount, char *inFilePath, int installCnt, int uninstallCnt)
{
	int count;
	
	for (;;)
	{Con_FgColor(0, 0);
		Con_Clear();
		
		if ((installCnt > 0) & (uninstallCnt == 0)) {
			printf("[+] %d fichier%s marque pour l'installation.\n", installCnt, (installCnt == 1) ? "" : "s");
			printf("    Continuer?\n");
		}
		else if ((installCnt == 0) & (uninstallCnt > 0)) {
			printf("[+] %d fichier%s marque pour la desinstallation.\n", uninstallCnt, (uninstallCnt == 1) ? "" : "s");
			printf("    Continuer?\n");
		}
		else {
			printf("[+] %d fichier%s marque pour l'installation et\n" , installCnt, (installCnt == 1) ? "" : "s");
            printf("    %d fichier%s pour la desinstallation.\n" , uninstallCnt, (uninstallCnt == 1) ? "" : "s");
			printf("    Continuer?\n");
		}
		
		printf("\n\n    Appuyez sur A pour continuer.\n");
		printf("    Appuyez sur B pour retourner au menu.\n\n");
		
		u32 buttons = WaitButtons();
		
		if (buttons & WPAD_BUTTON_A)
			break;
		
		if (buttons & WPAD_BUTTON_B)
			return 0;
	}
	
	WiiLightControl (WII_LIGHT_ON);
	int errors = 0;
	
	for (count = 0; count < fileCount; count++)
	{
		fatFile *thisFile = &files[count];
		
		if ((thisFile->install == 1) | (thisFile->install == 2)) {
			int mode = thisFile->install;
			Con_Clear();
			printf("[+] Ouverture \"%s\", patientez svp...\n\n", thisFile->filename);
		
			sprintf(gTmpFilePath, "%s/%s", inFilePath, thisFile->filename);	
			
			FILE *fp = fopen(gTmpFilePath, "rb");
			if (!fp) {Con_FgColor(1, 5);
				printf(" ERREUR!\n");
				errors += 1;
				continue;
				}
			
			printf("[+] %s WAD, patientez svp...\n", (mode == 2) ? "Desinstallation" : "Installation");		
			if (mode == 2)
				Wad_Uninstall(fp);
			else
				Wad_Install(fp);
		
			if (fp)
				fclose(fp);
		}
	}
		
	WiiLightControl (WII_LIGHT_OFF);
	
	printf("\n");
	
	if (errors > 0)Con_FgColor(1, 5);
		printf("    %d erreurs survenues...", errors);
		
	printf("    Appuyez sur un bouton pour continuer...\n");
	WaitButtons();
	
	return 1;
}



/* File Operations - Leathl */
int Menu_FileOperations(fatFile *file, char *inFilePath)
{
        f32 filesize = (file->filestat.st_size / MB_SIZE);
        
        for (;;)
        {WiiLightControl (WII_LIGHT_ON);
                 
                /* Clear console */
Con_FgColor(0, 0);
                Con_Clear();
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
                printf("[+] WAD nom : %s\n",          file->filename);
                printf("    WAD taille : %.2f MB\n\n\n", filesize);




                printf("[+] Selectionnez l'action: < %s WAD >\n\n",  "Supprime");


                printf("    Appuyez sur GAUCHE/DROITE pour selectionner l'action.\n\n");


                printf("    Appuyez sur A pour continuer.\n");
                printf("    Appuyez sur B pour retourner au menu.\n\n");
                printf("\t   Appuyez sur HOME ou START pour redemarrer.\n\n");
                break;
        default:case CONF_LANG_ENGLISH:
     


                printf("[+] WAD name : %s\n",          file->filename);
                printf("    WAD size : %.2f MB\n\n\n", filesize);




                printf("[+] Select the action: < %s WAD >\n\n", "Uninstall");


                printf("    Press LEFT/RIGHT to select the action.\n\n");


                printf("    Press A to continue.\n");
                printf("    Press B to return to the menu.\n\n");
                printf("\t   Press HOME ou START HOME or START for restart.\n\n");;
                break;
}       
                u32 buttons = WaitButtons();
                
                /* A button */
                if (buttons & WPAD_BUTTON_A)
                        break;


                /* B button */
                if (buttons & WPAD_BUTTON_B)
                        return 0;
        }
        
        Con_Clear();


        printf("[+] Suppression \"%s\", Patientez svp...\n", file->filename);
        
        sprintf(gTmpFilePath, "%s/%s", inFilePath, file->filename);
        int error = remove(gTmpFilePath);
        if (error != 0)
                printf("    ERREUR!");
        else 

                printf("    Suppression reussie!");
                
        printf("\n");
        printf("    Appuyez sur un bouton pour continuer...\n");


        WaitButtons();
        
        return !error;
}
                
void Menu_WadManage(fatFile *file, char *inFilePath)
{WiiLightControl (WII_LIGHT_ON);
        FILE *fp  = NULL;


        //char filepath[128];
        f32  filesize;


        u32  mode = 0;


        /* File size in megabytes */
        filesize = (file->filestat.st_size / MB_SIZE);


        for (;;) {
         
                /* Clear console */
Con_FgColor(0, 0);
                Con_Clear();
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
                printf("[+] WAD nom : %s\n",          file->filename);
                printf("    WAD taille : %.2f MB\n\n\n", filesize);




                printf("[+] Selectionnez l'action: < %s WAD >\n\n",  (!mode) ? "Installe" : "Supprime");


                printf("    Appuyez sur GAUCHE/DROITE pour selectionner l'action.\n\n");


                printf("    Appuyez sur A pour continuer.\n");
                printf("    Appuyez sur B pour retourner au menu.\n\n");
                printf("\t   Appuyez sur HOME ou START pour redemarrer.\n\n");
                break;
        default:case CONF_LANG_ENGLISH:
        


                printf("[+] WAD name : %s\n",          file->filename);
                printf("    WAD size : %.2f MB\n\n\n", filesize);




                printf("[+] Select the action: < %s WAD >\n\n",  (!mode) ? "Install" : "Uninstall");


                printf("    Press LEFT/RIGHT to select the action.\n\n");


                printf("    Press A to continue.\n");
                printf("    Press B to return to the menu.\n\n");
                printf("\t   Press HOME ou START HOME or START for restart.\n\n");
                break;
}


                u32 buttons = WaitButtons();


                /* LEFT/RIGHT buttons */
                if (buttons & (WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT))
                        mode ^= 1;


                /* A button */
                if (buttons & WPAD_BUTTON_A)
                        break;


                /* B button */
                if (buttons & WPAD_BUTTON_B)
                        return;
        }
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
        /* Clear console */
Con_FgColor(0, 0);
        Con_Clear();


        printf("[+] Ouverture \"%s\", attendez...", file->filename);
        fflush(stdout);


        /* Generate filepath */
        // sprintf(filepath, "%s:" WAD_DIRECTORY "/%s", fdev->mount, file->filename);
        sprintf(gTmpFilePath, "%s/%s", inFilePath, file->filename); // wiiNinja


        /* Open WAD */
        fp = fopen(gTmpFilePath, "rb");
        if (!fp) {Con_FgColor(1, 5);
                printf(" ERREUR! Dossier iswad absent!\n");
                goto out;
        } else 
Con_FgColor(2, 5);
                printf(" OK!\n\n");

Con_FgColor(0, 0);
        printf("[+] %s WAD, attendez...\n", (!mode) ? "Installe" : "Supprime");
break;
        default:case CONF_LANG_ENGLISH:
        /* Clear console */
        Con_Clear();


        printf("[+] Opening \"%s\", wait...", file->filename);
        fflush(stdout);


        /* Generate filepath */
        // sprintf(filepath, "%s:" WAD_DIRECTORY "/%s", fdev->mount, file->filename);
        sprintf(gTmpFilePath, "%s/%s", inFilePath, file->filename); // wiiNinja


        /* Open WAD */
        fp = fopen(gTmpFilePath, "rb");
        if (!fp) {
                printf(" ERREUR! Missing iswad folder!\n");
                goto out;
        } else
                printf(" OK!\n\n");


        printf("[+] %s WAD, wait...\n", (!mode) ? "Install" : "Uninstall");
            break;
}
        
        /* Do install/uninstall */
        WiiLightControl (WII_LIGHT_ON);
        if (!mode)
                Wad_Install(fp);
        else
                Wad_Uninstall(fp);
        WiiLightControl (WII_LIGHT_OFF);


out:
        /* Close file */
        if (fp)
                fclose(fp);
Con_FgColor(0, 0);
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:


        printf("\n");
        printf("   Rechargement...\n");
        printf("\t   Appuyez sur A pour continuer.\n");
                printf("\t   Appuyez sur HOME ou START pour redemarrer.\n\n");
                break;
        default:case CONF_LANG_ENGLISH:
        printf("\n");
        printf("   Reload...\n");
                printf("\n");
        printf("\t   Press A to contine.\n");
                printf("\t   Press HOME or START to restart.\n\n");
                break;
}


        //u32 buttons = Wpad_WaitButtons();
                u32 buttons = WaitButtons();


                
                /* Home button */
                if (buttons & WPAD_BUTTON_HOME)
                        Restart();
                        
                /* A button */
                if (buttons & WPAD_BUTTON_A)
                 return;
}


void Menu_WadList(void)
{WiiLightControl (WII_LIGHT_ON);
        char str [100];
        fatFile *fileList = NULL;
        u32      fileCnt;
        s32 ret, selected = 0, start = 0;
    char *tmpPath = malloc (MAX_FILE_PATH_LEN);
        int installCnt = 0;
        int uninstallCnt = 0;
        
        //fatFile *installFiles = malloc(sizeof(fatFile) * 50);
        //int installCount = 0;


    // wiiNinja: check for malloc error
    if (tmpPath == NULL)
    {
        ret = -999; // What am I gonna use here?
Con_FgColor(1, 5);
                printf(" ERREUR! Pas assez de memoire! (ret = %d)\n", ret);
        return;
    }

Con_FgColor(2, 5);
        printf("[+] Creation de la liste...");
        fflush(stdout);
        
        gDirLevel = 0;


    // wiiNinja: The root is always the primary folder
    // But if the user has a /wad directory, just go there. This makes
    // both sides of the argument win
        sprintf(tmpPath, "%s:" WAD_DIRECTORY, fdev->mount);
    PushCurrentDir(tmpPath,0,0);
        //if (strcmp (WAD_DIRECTORY, WAD_ROOT_DIRECTORY) != 0)
        if (strcmp (WAD_DIRECTORY, gConfig.startupPath) != 0)
        {
        // If the directory can be successfully opened, it must exists
        //DIR_ITER *tmpDirPtr = NULL;
        //tmpDirPtr = diropen(WAD_ROOT_DIRECTORY);
        //if (tmpDirPtr)
        //{
                //      dirclose (tmpDirPtr);


            // Now push the /wad directory as the current operating folder
            //sprintf(tmpPath, "%s:" WAD_ROOT_DIRECTORY, fdev->mount);
                        sprintf(tmpPath, "%s:%s", fdev->mount, gConfig.startupPath);
                        //printf ("\nThe final startupPath is: %s\n", tmpPath);
                        //WaitButtons ();
            PushCurrentDir(tmpPath,0,0); // wiiNinja
        //}
        }


        /* Retrieve filelist */
getList:
    if (fileList)
    {
        free (fileList);
        fileList = NULL;
    }


        ret = __Menu_RetrieveList(tmpPath, &fileList, &fileCnt);
        if (ret < 0) {
Con_FgColor(2, 5);
                printf(" ERREUR sur la liste!\n");
                goto err;
        }


        /* No files */
        if (!fileCnt) {
Con_FgColor(2, 5);
                printf(" Pas de fichier .wad\n");
                goto err;
        }
        
        /* Set install-values to 0 - Leathl */
        int counter;
        for (counter = 0; counter < fileCnt; counter++) {
                fatFile *file = &fileList[counter];
                file->install = 0;
        }


        for (;;) 
        {
                u32 cnt;
                s32 index;


                /* Clear console */
                Con_Clear();


                /** Print entries **/
                cnt = strlen(tmpPath);
                if(cnt>30)
                        index = cnt-30;
                else
                        index = 0;

Con_FgColor(0, 0);
                printf("[+] Fichiers WAD sur [%s]:\n\n", tmpPath+index);


                /* Print entries */
                for (cnt = start; cnt < fileCnt; cnt++) 
                {
                        fatFile *file     = &fileList[cnt];
                        f32      filesize = file->filestat.st_size / MB_SIZE;


                        /* Entries per page limit */
                        if ((cnt - start) >= ENTRIES_PER_PAGE)
                                break;


                        strncpy(str, file->filename, 48);
                        str[48]=0;
                        
                        /* Print filename */
                        //printf("\t%2s %s (%.2f MB)\n", (cnt == selected) ? ">>" : "  ", file->filename, filesize);
            if (file->filestat.st_mode & S_IFDIR) // wiiNinja
                                printf("\t%2s [%s]\n", (cnt == selected) ? ">>" : "  ", str);
            else
                printf("\t%2s%s%s (%.2f MB)\n", (cnt == selected) ? ">>" : "  ", (file->install == 1) ? "+" : ((file->install == 2) ? "-" : " "), str, filesize);


                }
Con_FgColor(0, 0);
switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
                printf("\n");


                printf("[+] Appuyez sur + ,- ,R ou L pour (de)selectionner les fichiers.\n");
                printf("    Appuyez sur A pour appliquer la selection.\n");
            printf("    Appuyez sur 1 pour supprimer un fichier du support.\n");
                        if(gDirLevel>1)
                printf("    Appuyez sur B pour choisir le dossier.\n");
                else
            printf("    Appuyez sur B pour selectionner le dossier.\n");
            printf("\t   Appuyez sur HOME ou START pour redemarrer.\n\n");
break;
        default:case CONF_LANG_ENGLISH:
        printf("\n");


                printf("[+] Press A to (un)install.");
                if(gDirLevel>1)
                        printf(" Press B to go up-level DIR.\n");
                else
                        printf(" Press B to select a device.\n");
                printf("    Use + ,- ,R ou L  to (un)mark. Press 1 for file operations.");
                printf("\t   Press HOME ou START HOME or START for restart.\n\n");
break;
}
                /** Controls **/
                u32 buttons = WaitButtons();


                /* DPAD buttons */
                if (buttons & (WPAD_BUTTON_UP | WPAD_BUTTON_LEFT)) {
                        selected -= (buttons & WPAD_BUTTON_LEFT) ? ENTRIES_PER_PAGE : 1;


                        if (selected <= -1)
                                selected = (fileCnt - 1);
                }
                if (buttons & (WPAD_BUTTON_DOWN | WPAD_BUTTON_RIGHT)) {
                        selected += (buttons & WPAD_BUTTON_RIGHT) ? ENTRIES_PER_PAGE : 1;


                        if (selected >= fileCnt)
                                selected = 0;
                }


                /* HOME button */
                if (buttons & WPAD_BUTTON_HOME)
                        Restart();


                /* Plus Button - Leathl */
                if (buttons & WPAD_BUTTON_PLUS)
                {
                        fatFile *file = &fileList[selected];
                        if (((file->filestat.st_mode & S_IFDIR) == false) & (file->install == 0)) {     
                                file->install = 1;
                                
                                installCnt += 1;
                        }
                        else if (((file->filestat.st_mode & S_IFDIR) == false) & (file->install == 1)) {        
                                file->install = 0;
                                
                                installCnt -= 1;
                        }
                        else if (((file->filestat.st_mode & S_IFDIR) == false) & (file->install == 2)) {        
                                file->install = 1;
                                
                                installCnt += 1;
                                uninstallCnt -= 1;
                        }
                }
                
                /* Minus Button - Leathl */
                if (buttons & WPAD_BUTTON_MINUS)
                {               
                        fatFile *file = &fileList[selected];
                        if (((file->filestat.st_mode & S_IFDIR) == false) & (file->install == 0)) {     
                                file->install = 2;
                                
                                uninstallCnt += 1;
                        }
                        else if (((file->filestat.st_mode & S_IFDIR) == false) & (file->install == 1)) {        
                                file->install = 2;
                                
                                uninstallCnt += 1;
                                installCnt -= 1;
                        }
                        else if (((file->filestat.st_mode & S_IFDIR) == false) & (file->install == 2)) {        
                                file->install = 0;
                                
                                uninstallCnt -= 1;
                        }
                }
                
                /* 1 Button - Leathl */
                if (buttons & WPAD_BUTTON_1)
                {
                        fatFile *tmpFile = &fileList[selected];
                        char *tmpCurPath = PeekCurrentDir ();
            if (tmpCurPath != NULL) {
                                int res = Menu_FileOperations(tmpFile, tmpCurPath);
                if (res != 0)
                                        goto getList;
                        }
                }


                
                /* A button */
                if (buttons & WPAD_BUTTON_A)
                {
                                fatFile *tmpFile = &fileList[selected];
                                char *tmpCurPath;
                                if (tmpFile->filestat.st_mode & S_IFDIR) // wiiNinja
                                {
                                        if (strcmp (tmpFile->filename, "..") == 0)
                                        {
                                                selected = 0;
                                                start = 0;


                                                // Previous dir
                                                tmpCurPath = PopCurrentDir(&selected, &start);
                                                if (tmpCurPath != NULL)
                                                        sprintf(tmpPath, "%s", tmpCurPath);
                                                
                                                installCnt = 0;
                                                uninstallCnt = 0;
                                                
                                                goto getList;
                                        }
                                        else if (IsListFull () == true)
                                        {
                                                WaitPrompt ("Nombre de sous-dossiers atteind!\n");
                                        }
                                        else
                                        {
                                                tmpCurPath = PeekCurrentDir ();
                                                if (tmpCurPath != NULL)
                                                {
                                                        if(gDirLevel>1)
                                                                sprintf(tmpPath, "%s/%s", tmpCurPath, tmpFile->filename);
                                                        else
                                                                sprintf(tmpPath, "%s%s", tmpCurPath, tmpFile->filename);
                                                }
                                                // wiiNinja: Need to PopCurrentDir
                                                PushCurrentDir (tmpPath, selected, start);
                                                selected = 0;
                                                start = 0;
                                                
                                                installCnt = 0;
                                                uninstallCnt = 0;
                                                
                                                goto getList;
                                        }
                                }
                                else
                                {
                                        //If at least one WAD is marked, goto batch screen - Leathl
                                        if ((installCnt > 0) | (uninstallCnt > 0)) {
                                                char *thisCurPath = PeekCurrentDir ();
                                                if (thisCurPath != NULL) {
                                                        int res = Menu_BatchProcessWads(fileList, fileCnt, thisCurPath, installCnt, uninstallCnt);
                                        
                                                        if (res == 1) {
                                                                int counter;
                                                                for (counter = 0; counter < fileCnt; counter++) {
                                                                        fatFile *temp = &fileList[counter];
                                                                        temp->install = 0;
                                                                }
                                        
                                                                installCnt = 0;
                                                                uninstallCnt = 0;
                                                        }
                                                }
                                        }
                                        //else use standard wadmanage menu - Leathl
                                        else {
                                                tmpCurPath = PeekCurrentDir ();
                                                if (tmpCurPath != NULL)
                                                        Menu_WadManage(tmpFile, tmpCurPath);
                                        }
                                }
                }


                /* B button */
                if (buttons & WPAD_BUTTON_B)
                {
                        if(gDirLevel<=1)
                        {
                                return;
                        }


                        char *tmpCurPath;
                        selected = 0;
                        start = 0;
                        // Previous dir
                        tmpCurPath = PopCurrentDir(&selected, &start);
                        if (tmpCurPath != NULL)
                                sprintf(tmpPath, "%s", tmpCurPath);
                        goto getList;
                        //return;
                }


                /** Scrolling **/
                /* List scrolling */
                index = (selected - start);


                if (index >= ENTRIES_PER_PAGE)
                        start += index - (ENTRIES_PER_PAGE - 1);
                if (index <= -1)
                        start += index;
        }


err:
WiiLightControl (WII_LIGHT_OFF);
        switch (CONF_GetLanguage()) {
                case CONF_LANG_FRENCH:
        printf("\n");
        printf("   Appuyez sur un bouton pour continuer...\n");
        break;
        default:case CONF_LANG_ENGLISH:


        printf("\n");
        printf("    Press a button to continue...\n");
        break;
}
        free (tmpPath);
        
        /* Wait for button */
        WaitButtons();
}




void Menu_Loop(void)
{
        u8 iosVersion;


        /* Select IOS menu */
        Menu_SelectIOS();


        /* Retrieve IOS version */
        iosVersion = IOS_GetVersion();


        /* NAND device menu */
        if (iosVersion == CIOS_VERSION)
                Menu_NandDevice();


        for (;;) {
                /* FAT device menu */
                Menu_FatDevice();


                /* WAD list menu */
                Menu_WadList();
        }
}


// Start of wiiNinja's added routines


int PushCurrentDir (char *dirStr, s32 Selected, s32 Start)
{
    int retval = 0;


    // Store dirStr into the list and increment the gDirLevel
    // WARNING: Make sure dirStr is no larger than MAX_FILE_PATH_LEN
    if (gDirLevel < MAX_DIR_LEVELS)
    {
        strcpy (gDirList [gDirLevel], dirStr);
                gSeleted[gDirLevel]=Selected;
                gStart[gDirLevel]=Start;
        gDirLevel++;
        //if (gDirLevel >= MAX_DIR_LEVELS)
        //    gDirLevel = 0;
    }
    else
        retval = -1;


    return (retval);
}


char *PopCurrentDir(s32 *Selected, s32 *Start)
{
        if (gDirLevel > 1)
        gDirLevel--;
    else
        gDirLevel = 0;


        *Selected = gSeleted[gDirLevel];
        *Start = gStart[gDirLevel];
        return PeekCurrentDir();
}


bool IsListFull (void)
{
    if (gDirLevel < MAX_DIR_LEVELS)
        return (false);
    else
        return (true);
}


char *PeekCurrentDir (void)
{
    // Return the current path
    if (gDirLevel > 0)
        return (gDirList [gDirLevel-1]);
    else
        return (NULL);
}


void WaitPrompt (char *prompt)
{
        printf("\n%s", prompt);
        printf("    Appuyez sur un bouton pour continuer...\n");


        /* Wait for button */
        WaitButtons();
}


u32 Pad_GetButtons(void)
{
        u32 buttons = 0, cnt;


        /* Scan pads */
        PAD_ScanPads();


        /* Get pressed buttons */
        //for (cnt = 0; cnt < MAX_WIIMOTES; cnt++)
        for (cnt = 0; cnt < 4; cnt++)
                buttons |= PAD_ButtonsDown(cnt);


        return buttons;
}




// Routine to wait for a button from either the Wiimote or a gamecube
// controller. The return value will mimic the WPAD buttons to minimize
// the amount of changes to the original code, that is expecting only
// Wiimote button presses. Note that the "HOME" button on the Wiimote
// is mapped to the "SELECT" button on the Gamecube Ctrl. (wiiNinja 5/15/2009)
u32 WaitButtons(void)
{
        u32 buttons = 0;
    u32 buttonsGC = 0;


        /* Wait for button pressing */
        while (!buttons && !buttonsGC)
    {
        // GC buttons
        buttonsGC = Pad_GetButtons ();


        // Wii buttons
                buttons = Wpad_GetButtons();


                VIDEO_WaitVSync();
        }


    if (buttonsGC)
    {
        if(buttonsGC & PAD_BUTTON_A)
        {
            //printf ("Button A on the GC controller\n");
            buttons |= WPAD_BUTTON_A;
        }
        else if(buttonsGC & PAD_BUTTON_B)
        {
            //printf ("Button B on the GC controller\n");
            buttons |= WPAD_BUTTON_B;
        }
        else if(buttonsGC & PAD_BUTTON_LEFT)
        {
            //printf ("Button LEFT on the GC controller\n");
            buttons |= WPAD_BUTTON_LEFT;
        }
        else if(buttonsGC & PAD_BUTTON_RIGHT)
        {
            //printf ("Button RIGHT on the GC controller\n");
            buttons |= WPAD_BUTTON_RIGHT;
        }
        else if(buttonsGC & PAD_BUTTON_DOWN)
        {
            //printf ("Button DOWN on the GC controller\n");
            buttons |= WPAD_BUTTON_DOWN;
        }
        else if(buttonsGC & PAD_BUTTON_UP)
        {
            //printf ("Button UP on the GC controller\n");
            buttons |= WPAD_BUTTON_UP;
        }
        else if(buttonsGC & PAD_BUTTON_START)
        {
            //printf ("Button START on the GC controller\n");
            buttons |= WPAD_BUTTON_HOME;
        }
        else if(buttonsGC & PAD_TRIGGER_R)
        {
            //printf ("Button START on the GC controller\n");
            buttons |= WPAD_BUTTON_MINUS;
        }
        else if(buttonsGC & PAD_TRIGGER_L)
        {
            //printf ("Button START on the GC controller\n");
            buttons |= WPAD_BUTTON_PLUS;
        }
    }


        return buttons;
} // WaitButtons




void WiiLightControl (int state)
{
        switch (state)
        {
                case WII_LIGHT_ON:
                        /* Turn on Wii Light */
                        WIILIGHT_SetLevel(255);
                        WIILIGHT_TurnOn();
                        break;


                case WII_LIGHT_OFF:
                default:
                        /* Turn off Wii Light */
                        WIILIGHT_SetLevel(0);
                        WIILIGHT_TurnOn();
                        WIILIGHT_Toggle();
                        break;
        }
} // WiiLightControl


